/*******************************************************************************
 * Includes
 ******************************************************************************/
#include "slab/Wed_slab.h"
//#include "memheap/Wed_memheap.h"
#include "memheap2/Wed_memheap2.h"

#if WED_MEM_DYMANICS
/*******************************************************************************
 * Static
 ******************************************************************************/
/* \brief 动态内存缓存 */
static uint8_t            __g_dymanics_mem_buf[WED_MEM_DYMANICS_SIZE];
#if WED_MEM_USE_MEMHEAP
// static struct Wed_memheap __g_mem_heap;
static struct Wed_memheap2 __g_mem_heap;
#endif
static struct Wed_memheap2 __g_mem_dma_heap;

/*******************************************************************************
 * Code
 ******************************************************************************/
/**
 * \brief 内存初始化
 *
 * @return 成功返回 0
 */
int Wed_mem_init(void){
#if WED_MEM_USE_MEMHEAP
    // Wed_memheap_init(&__g_mem_heap, (void *)__g_dymanics_mem_buf, WED_MEM_DYMANICS_SIZE);
    return Wed_memheap2_init(&__g_mem_heap, (void *)__g_dymanics_mem_buf, WED_MEM_DYMANICS_SIZE);
#else
    /* 初始化 SLAB 内存管理 */
    return Wed_slab_init((void *)__g_dymanics_mem_buf, WED_MEM_DYMANICS_SIZE);
#endif
}

/**
 * \brief 内存分配函数
 *
 * @param size 要分配内存的大小
 *
 * @return 成功返回分配的内存地址
 */
void *Wed_malloc(uint32_t size){
#if WED_MEM_USE_MEMHEAP
    // return Wed_memheap_malloc(&__g_mem_heap, size);
    return Wed_memheap2_malloc(&__g_mem_heap, size);
#else
#endif
}

/**
 * \brief 内存释放函数
 *
 * @param p_mem 要释放的内存的地址
 */
void Wed_free(void *p_mem){
#if WED_MEM_USE_MEMHEAP
    // Wed_memheap_free(&__g_mem_heap, p_mem);
    Wed_memheap2_free(p_mem);
#else
#endif
}

/**
 * \brief 指定数量和大小的内存块，并将分配的内存初始化为零
 *
 * @param n_mems 要分配内存块的数量
 * @param size   要分配内存块的大小
 *
 * @return 成功返回分配的内存地址
 */
void *Wed_calloc(uint32_t n_mems, uint32_t size){
    void *p_mem = Wed_malloc(n_mems * size);
    if (p_mem) {
        memset(p_mem, 0, n_mems * size);
    }
    return p_mem;
}

#define WED_MEMITEM_SIZE_GET(p_item)    ((uint32_t)p_item->p_item_next - (uint32_t)p_item - WED_MEMHEAP2_ITEM_SIZE)
/**
 * \brief 重新分配内存
 *
 * @param p_mem    旧的内存地址
 * @param new_size 分配的新的内存的大小
 *
 * \retval 成功返回新分配的内存地址
 */
void *Wed_realloc(void *p_mem, uint32_t new_size){
    uint32_t                  old_size;
    void                     *p_mem_new = NULL;
    struct Wed_memheap2_item *p_hdr     = NULL;

    if (p_mem) {
        /* 移动到条目头部 */
        p_hdr = (struct Wed_memheap2_item *)((uint8_t *)p_mem - WED_MEMHEAP2_ITEM_SIZE);

        /* 检查魔法数 */
        if ((p_hdr->magic & WED_MEMHEAP2_MAGIC_MASK) != WED_MEMHEAP2_MAGIC) {
            WED_ERR_PRINT("memory item magic %d illegal", p_hdr->magic);
            while(1);
        }

        old_size = WED_MEMITEM_SIZE_GET(p_hdr);

        if (old_size != new_size) {
            p_mem_new = Wed_malloc(new_size);
            if (p_mem_new == NULL) {
                return NULL;
            }
            memset(p_mem_new, 0, new_size);

            memcpy(p_mem_new, p_mem, (new_size > old_size)? old_size : new_size);

            Wed_free(p_mem);

            return p_mem_new;
        } else {
            return p_mem;
        }
    }
    return Wed_malloc(new_size);
}

/**
 * \brief DMA 内存初始化
 *
 * @return 成功返回 0
 */
int Wed_mem_dma_init(void *p_start_addr, uint32_t size){
    return Wed_memheap2_init(&__g_mem_dma_heap, p_start_addr, size);
}

/**
 * \brief DMA 内存分配
 *
 * @param size  要分配的内存大小
 * @param align 内存起始地址对齐数
 *
 * @return 成功返回分配的内存地址
 */
void *Wed_mem_dma_align_alloc(uint32_t size, uint32_t align){
    return Wed_memheap2_align_malloc(&__g_mem_dma_heap, size, align);
}

/**
 * \brief DMA 内存释放
 *
 * @param p_mem 要释放的内存地址
 */
void Wed_mem_dma_align_free(void *p_mem){
    Wed_memheap2_align_free(p_mem);
}
#endif

